<!DOCTYPE html>
<html lang="ru">
	<head>
		<meta charset="utf-8">
		<base href="../../../" />
		<script src="page.js"></script>
		<link type="text/css" rel="stylesheet" href="page.css" />
	</head>
	<body>
		<h1>Создание сцены</h1>

		<p>Цель этого раздела - дать краткое введение в three.js . Мы начнем с создания сцены с вращающимся кубом. Рабочий пример приведен внизу страницы на случай, если вы где то застряли и вам понадобится помощь.</p>

		<h2>Прежде чем мы начнем</h2>

		<p>
			Прежде чем вы сможете использовать three.js , вам нужно где-то его отобразить. Save the following HTML to a file on your computer and open it in your browser.
		</p>

		<code>
		&lt;!DOCTYPE html&gt;
		&lt;html&gt;
			&lt;head&gt;
				&lt;meta charset="utf-8"&gt;
				&lt;title&gt;My first three.js app&lt;/title&gt;
				&lt;style&gt;
					body { margin: 0; }
				&lt;/style&gt;
			&lt;/head&gt;
			&lt;body&gt;
				&lt;script type="module"&gt;
					import * as THREE from 'https://cdn.jsdelivr.net/npm/three/build/three.module.js';

					// Наш Javascript будет здесь..
				&lt;/script&gt;
			&lt;/body&gt;
		&lt;/html&gt;
		</code>

		<p>Пока это все. Весь приведенный ниже код помещается в пустой тег &lt;script&gt;.</p>

		<h2>Создание сцены</h2>

		<p>Чтобы на самом деле иметь возможность отображать что-либо с three.js, Нам нужны три вещи: сцена, камера и средство визуализации, чтобы мы могли визуализировать сцену с помощью камеры.</p>

		<code>
		const scene = new THREE.Scene();
		const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

		const renderer = new THREE.WebGLRenderer();
		renderer.setSize( window.innerWidth, window.innerHeight );
		document.body.appendChild( renderer.domElement );
		</code>

		<p>Давайте воспользуемся моментом, чтобы объяснить, что здесь происходит. Теперь мы настроили сцену, нашу камеру и средство визуализации.</p>

		<p>Есть несколько разных камер в three.js . А пока давайте воспользуемся `PerspectiveCamera`.</p>
		<p>Первый атрибут - это `поле зрения (field of view)`. FOV - это масштаб сцены, которая видна на дисплее в любой данный момент. Значение указано в градусах.</p>

		<p>Второй - это `соотношение сторон (aspect ratio)`. Вы почти всегда хотите использовать ширину элемента, деленную на высоту, иначе вы получите тот же результат, что и при воспроизведении старых фильмов на широкоэкранном телевизоре - изображение выглядит сплющенным.</p>

		<p>Следующие два атрибута - это `ближняя (near)` и `дальняя (far)` плоскость отсечения. Это означает, что объекты, находящиеся дальше от камеры, чем значение `far`, или ближе, чем `near`, не будут отображаться. Сейчас вам не нужно беспокоиться об этом, но вы можете использовать другие значения в своих приложениях, чтобы повысить производительность.</p>

		<p>Далее следует средство визуализации. Вот тут-то и происходит волшебство. В дополнение к средству визуализации WebGL, которое мы используем здесь, three.js поставляется с несколькими другими, часто используемыми в качестве резервных для пользователей со старыми браузерами или для тех, у кого по какой-либо причине нет поддержки WebGL.</p>
		<p>В дополнение к созданию экземпляра средства визуализации нам также необходимо установить размер, в котором мы хотим, чтобы оно отображало наше приложение. Рекомендуется использовать ширину и высоту области, которую мы хотим заполнить с помощью нашего приложения - в данном случае ширину и высоту окна браузера. Для приложений с высокой производительностью вы также можете задать `setSize` меньшее значения, например `window.innerWidth/2` и `window.innerHeight/2`, что приведет к рендерингу приложения в четверть размера.</p>
		<p>Если вы хотите сохранить размер своего приложения, но отобразить его с меньшим разрешением, вы можете сделать это, вызвав `setSize` с `updateStyle`(третий аргумент) равному false. Например, `setSize(window.innerWidth/2, window.innerHeight/2, false)` будет отображать ваше приложение с половинным разрешением, учитывая, что ваш &lt;canvas &gt; имеет 100% ширины и высоты.</p>

		<p>И последнее, но не менее важное: мы добавляем элемент `renderer` в наш HTML-документ. Это элемент &lt;canvas&gt;, который рендерер использует для отображения сцены для нас.</p>
		<p><em>"Все это хорошо, но, где тот кубик, который Вы так обещали?"</em> Давайте добавим его сейчас.</p>

		<code>
		const geometry = new THREE.BoxGeometry( 1, 1, 1 );
		const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
		const cube = new THREE.Mesh( geometry, material );
		scene.add( cube );

		camera.position.z = 5;
		</code>

		<p>Чтобы создать куб, нам нужна `BoxGeometry`. Это объект, который содержит все точки (`vertices/вершины`) и заливку (`faces/грани`) куба. Мы подробнее рассмотрим это в будущем.</p>

		<p>В дополнение к геометрии нам нужен материал, чтобы раскрасить его. Three.js поставляется с несколькими материалами, но пока мы будем придерживаться `MeshBasicMaterial`. Все материалы приобретают объект свойств, которые будут к ним применены. Чтобы все было очень просто, мы предоставляем только атрибут цвета `0x00ff00`, который является зеленым. Это работает так же, как цвета работают в CSS или Photoshop (`шестнадцатеричные цвета/hex colors`).</p>

		<p>Третья вещь, которая нам нужна, - это `Mesh(Сетка)`. Сетка - это объект, который принимает геометрию и применяет к ней материал, который затем мы можем вставить в нашу сцену и свободно перемещать по ней.</p>

		<p>По умолчанию, когда мы вызываем `scene.add()`, то, что мы добавляем, будет добавлено к координатам `(0,0,0)`. Это привело бы к тому, что и камера, и куб оказались бы внутри друг друга. Чтобы избежать этого, мы просто немного выдвигаем камеру.</p>

		<h2>Рендеринг сцены</h2>

		<p>Если бы вы скопировали приведенный выше код в HTML-файл, который мы создали ранее, вы бы ничего не смогли увидеть. Это потому, что на самом деле мы еще ничего не рендерим. Для этого нам нужно то, что называется `цикл рендеринга или анимации`.</p>

		<code>
		function animate() {
			requestAnimationFrame( animate );
			renderer.render( scene, camera );
		}
		animate();
		</code>

		<p> Это создаст цикл, который заставляет средство визуализации отрисовывать сцену каждый раз при обновлении экрана (на обычном экране это означает 60 раз в секунду). Если вы новичок в написании игр в браузере, вы можете сказать <em> "Почему бы нам просто не создать setInterval?"</em> Дело в том, что мы могли бы, но `requestAnimationFrame` имеет ряд преимуществ. Возможно, самым важным из них является то, что он приостанавливается, когда пользователь переходит на другую вкладку браузера, следовательно, не тратя впустую свою драгоценную вычислительную мощность и время автономной работы.</p>

		<h2>Анимация куба</h2>

		<p>Если вы вставите весь приведенный выше код в файл, который вы создали до того, как мы начали, вы должны увидеть зеленое поле. Давайте сделаем все это немного интереснее, повернув его.</p>

		<p>Добавьте следующий код прямо над вызовом `renderer.render` в вашей функции `animate`:</p>

		<code>
		cube.rotation.x += 0.01;
		cube.rotation.y += 0.01;
		</code>

		<p> Это будет выполняться каждый кадр (обычно 60 раз в секунду) и придаст кубу приятную анимацию вращения. По сути, все, что вы хотите переместить или изменить во время работы приложения, должно пройти через цикл анимации. Конечно, вы можете вызывать оттуда другие функции, чтобы в итоге не получить `анимированную` функцию, состоящую из сотен строк.</p>

		<h2>Результат</h2>

		<p>Поздравляю! Теперь вы завершили свой первый three.js применение. Это просто, но вы должны с чего-то начать.</p>

		<p>Полный код доступен ниже и доступен для редактирования [link:https://jsfiddle.net/0c1oqf38/ live example]. Поиграйте с ним, чтобы лучше понять, как он работает.</p>

		<code>
		&lt;!DOCTYPE html&gt;
		&lt;html&gt;
			&lt;head&gt;
				&lt;meta charset="utf-8"&gt;
				&lt;title&gt;My first three.js app&lt;/title&gt;
				&lt;style&gt;
					body { margin: 0; }
				&lt;/style&gt;
			&lt;/head&gt;
			&lt;body&gt;
				&lt;script type="module"&gt;
					import * as THREE from 'https://cdn.jsdelivr.net/npm/three/build/three.module.js';

					const scene = new THREE.Scene();
					const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

					const renderer = new THREE.WebGLRenderer();
					renderer.setSize( window.innerWidth, window.innerHeight );
					document.body.appendChild( renderer.domElement );

					const geometry = new THREE.BoxGeometry( 1, 1, 1 );
					const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
					const cube = new THREE.Mesh( geometry, material );
					scene.add( cube );

					camera.position.z = 5;

					function animate() {
						requestAnimationFrame( animate );

						cube.rotation.x += 0.01;
						cube.rotation.y += 0.01;

						renderer.render( scene, camera );
					}

					animate();
				&lt;/script&gt;
			&lt;/body&gt;
		&lt;/html&gt;
		</code>
	</body>
</html>
